在C#中以Class{...}來定義一個類別,類別定義是一個全域宣告的概念,要放在namespace{...}內,但不能放在方法中。類別內可以有建構函式 (Constructor)、屬性 (Properties)、欄位 (Field)、方法 (Method)
Class架構如下(以console模式為例):
(圖片繪製參考:[C#][Visual Studio] 類別與物件 (class and object))
類別、類別資料成員們(方法、屬性、欄位、建構函式)可以使用存取修飾詞宣告存取範圍,控制可以從哪裡使用它們,預設值為private,其他存取修飾詞如下:
存取修飾詞 | 作用 | 存取範圍 |
---|---|---|
public | 公開 | 無限制 |
private(預設) | 私有 | 只有本身類別可以存取 |
protected | 保護 | 父類別或繼承自父類別的子類別(衍生類別) |
internal | 內部 | 限於目前專案(組件) |
protected internal | 限於目前專案或是繼承自父類別 | |
private protected | 存取限於目前專案內包含類別或衍生自包含類別的類型。自C#7.2起可用。 |
注意:namespace是不能使用存取修飾詞的
完成類別設定之後,必須實體化為物件,透過new這個關鍵字來初始化
SayHi yo =new SayHi();
你如果有使用聰明的IDE及套件,可能會看過這個畫面
這代表DateTime這個類別在宣告時,你有很多種方式可以給定參數並初始化那個物件
也就是建構子可以設定是否要接受參數來初始化一個新的物件,與宣告方法很相似,有幾點需要注意:
範例(取自MSDN-使用建構函式):
public class Employee//建立一個Employee的類別
{
public int Salary;//設定一個叫Salary的欄位
public Employee(int annualSalary)//第一個建構函式,帶入一個int參數,初始化時會將參數賦值給Salary
{
Salary = annualSalary;
}
public Employee(int weeklySalary, int numberOfWeeks)//第二個建構函式,帶入2個int參數,初始化時會將參數第一個參數與第二個參數相乘後,賦值給Salary
{
Salary = weeklySalary * numberOfWeeks;
}
}
於是接下來當要new 一個Employee類別的物件時,可以使用下列任一陳述式建立
Employee staff = new Employee(30000);
Employee manager = new Employee(500, 52);
這兩個使用上很像一般變數,呼叫也都是用"."
物件.欄位
物件.屬性
但有時候我們既希望他可以像變數一樣被使用,又想要偷偷的對這個變數做一些處理,不讓使用的人知道,這時候就可以採用支援存放(baking store)的作法,配合存取子(Accessor)的get/set做存取以及額外的處理。
舉例來說,我們要設定一個快樂體重計的屬性是重量weight,小於就顯示0,大於也只會顯示60。
若只是單純宣告public會被發現,也能夠隨意設定超出範圍的值,這時可以如下方這樣寫
class Program
{
static void Main(string[] args)
{
scales scales =new scales();
scales.weight = 200;
Console.WriteLine($"你的體重是{scales.weight}");
Console.ReadKey();
}
public class scales//定義scales類別
{
private int newWeight;//newWeight為private,只能在scales內使用
public int weight
{
get//get存取子可以回傳屬性值
{
return newWeight;//使用return回傳屬性值
}
set//set存取子可以設定屬性值,value是外部傳來的數字
{
if (value < 0)//如果小於0就設為0
{
value = 0;
}
if (value > 60)//大於60就顯示60
{
value = 60;
}
newWeight = value;//把調整後的value值賦值給newWeight
}
}
}
}
輸出結果:
當使用scales.weight=200設定屬性值時,程式會執行set{...}區段,value的值就是200,value經過處理後把值賦值給內部變數newWeight,接下來要讀取scales.weight的值時,會執行get{...}區段,傳回newWeight
唯讀: 不放set{...}即可
唯寫: 不放get{...}即可
在類別內使用get和set存取子設定屬性最大優點是可以隱藏我們真的要做的事情(資料封裝),但如果我們只是要達到資料封裝但實際上沒有要做任何調整,寫法會像下方程式碼一樣:
public class scales
{
private int newWeight;
public int weight
{
get{return newWeight;}
set{newWeight = value;}
}
}
這樣有點太繁瑣了,Visual C#2008版本開始提供自動屬性實作,存放屬性的私有變數會由編譯器自動建立,所以可以改寫成下方這樣,精簡多了!
public class scales
{
public int weight{get;set;}
}
方法是包含一系列陳述式的程式碼區塊,例如Main()就是一個方法。建立方法的方式與建構子很類似,如下方
static void Main(string[] args)
{
int amount =1000;
int newAmount = addMoney(amount);//呼叫addMoney的方法並賦值給newAmount
Console.WriteLine(amount);//amount的值不會改變
Console.WriteLine(newAmount);
Console.ReadKey();
}
private static int addMoney(int amount)
{
amount = amount * 2;
return amount;
}
輸出結果:
預設為傳值呼叫Call By Value,amount的值是不會改變的!
如果希望amount的值跟著改變,需要使用參考呼叫Call By Reference,加上"ref"在方法宣告及使用上,如下方
static void Main(string[] args)
{
int amount =1000;
int newAmount = addMoney(ref amount);//呼叫addMoney的方法並賦值給newAmount
Console.WriteLine(amount);//有ref,amount的值會改變
Console.WriteLine(newAmount);
Console.ReadKey();
}
private static int addMoney(ref int amount)
{
amount = amount * 2;
return amount;
}
輸出結果:
這樣amount的值就會被改變了!
呼叫方式也是用"."的運算子,與屬性最大差別為方法後方一定跟著"( )"。
同時也 支援多載 ,同一個方法名稱可以依據參數不同執行不同功能的方法,如下方
static void Main(string[] args)
{
int newAmount = addMoney(1000);//呼叫addMoney的方法並賦值給newAmount,由於是傳入int參數,會執行第一個方法
Console.WriteLine(newAmount);
string name = addMoney("Cynthia~");//呼叫addMoney的方法並賦值給name,由於是傳入string參數,所以會執行第二個方法
Console.WriteLine(name);
Console.ReadKey();
}
private static int addMoney(int amount)//第一個方法
{
amount = amount * 2;
return amount;
}
private static string addMoney(string amount)//第二個方法
{
amount = amount+"hi";
return amount;
}
到這裡有沒有發現之前我們寫的小工具例如檢查身分證字號的程式,可以把它包成一個方法,這樣就可以呼叫該方法執行打包後的程式碼,不用落落長的擠在主程式裡,可以變得更好維護喔~
[C#][Visual Studio] 類別與物件 (class and object)
MSDN-存取範圍層級
MSDN-存取修飾詞
MSDN-使用建構函式
從零開始學Visual C# 2017程式設計
Visual C# 2017程式設計經典
參數的 by value, by reference 就足以講一整篇了。
只有實值型態 (value type) 才會有這種差異,若參數是參考型態 (reference type) 就只有 by reference 一種傳法而已。
類別、屬性、方法等的命名要開始學習了,建議可參考網路上有些高手或前輩釋出的命名規範來做,像是類別要用大寫字母開頭、屬性和方法也是用大寫字母 (Java則是小寫字母) 開頭之類的。
1.立馬研究了這兩者寫成文章XD
2.好的orz...感謝大大提醒